Skip to content

[xtask] Add aggro subcommand for building aggregate docs#2481

Draft
jamesmunns wants to merge 9 commits intomasterfrom
james/xtask-aggro
Draft

[xtask] Add aggro subcommand for building aggregate docs#2481
jamesmunns wants to merge 9 commits intomasterfrom
james/xtask-aggro

Conversation

@jamesmunns
Copy link
Copy Markdown
Contributor

@jamesmunns jamesmunns commented Apr 17, 2026

I've currently plumbed a good "base coat" of the aggro subcommand (name bikeshedding welcome, it was funny on a Friday morning), which generally:

  • Takes a task config
  • Figures out all the tasks in that config
  • Splats all of the READMEs (that are present) into a single bundle, and renders them into a single HTML "report".

Currently, it looks like this:

Screenshot 2026-04-20 at 15-53-02 cosmo-b Aggregate Docs

aggro.html

From now, there are a couple of questions:

  1. I could use some feedback on "matters of taste":
  • What information WOULD be useful to document on a per-app, or a per-task basis?
  • I included some simple tables, but these should be considered a proof of concept.
  • How do we want to shape this? One big MD/HTML/PDF file? Something more multi-page organized like mdbook?
  1. I think we'll want to make a pass over our task docs:
  • Most tasks don't have any docs! But we can backfill this :)
  • We probably want to set out a bit of a "standard" of how drivers+tasks+apps are documented

I did try figuring out how to insert the task graph, sadly the launch-rs crate isn't as good at layouting as the dot bin is, and neither are great for making legible diagrams. We may want to break this up on a per-task basis just to reduce the number of entities per-graph.

Screenshot 2026-04-17 at 7 33 04 PM

@jamesmunns jamesmunns requested review from cbiffle and mkeeter April 17, 2026 18:55
@jamesmunns
Copy link
Copy Markdown
Contributor Author

Thing to add: UDP sockets by task + port

Comment thread build/xtask/src/aggro.rs
pub fn run(app_toml: &Path, output: Option<&Path>) -> Result<()> {
let cfg = Config::from_file(app_toml)?;

println!("{}", std::env::current_dir().unwrap().display());
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove debug print?

Comment thread build/xtask/src/aggro.rs
// Exactly one match
[found] => Some(found.clone()),
_ => {
panic!("too many readmes");
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've vote to log an error (including the task name) and continue instead of panicking, on the rare chance that a task has both readme.md and readme.mkdn.

Comment thread build/xtask/src/aggro.rs
writeln!(&mut mkdn)?;
writeln!(
&mut mkdn,
"| task: crate | priority | stack (bytes) | interrupts | client of | server for |"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find "client of" / "server for" confusing, maybe "called by" and "calls into"?

Comment thread build/xtask/src/aggro.rs
let stack = if let Some(amt) = task.stacksize {
amt.to_string()
} else {
"???".to_string()
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use cfg.stacksize as fallback before declaring defeat here.

Comment thread build/xtask/src/aggro.rs
//
// Write this as markdown for laziness, then HTMLify it
let mut mkdn = String::new();
writeln!(&mut mkdn, "# `{}` docs", task.name)?;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove this, since it just adds busyness to the page.

Comment thread build/xtask/src/aggro.rs
let mut mkdn = String::new();
writeln!(&mut mkdn, "# `{}` docs", task.name)?;
writeln!(&mut mkdn)?;
writeln!(&mut mkdn, "(this page intentionally left blank)")?;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
writeln!(&mut mkdn, "(this page intentionally left blank)")?;
writeln!(&mut mkdn, "(no README available)")?;

to make it more clear what's going on

Comment thread build/xtask/src/aggro.rs
} => {
if !dest_url.starts_with("http") {
// TODO: rewrite relative to `https://github.com/oxidecomputer/hubris/blob/master/`?
// use _base to figure out relative paths, we might also need to
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might also need to what??

Comment thread build/xtask/src/graph.rs
/// Generate a directed graph of task priorities and task_slot
/// dependencies.
pub fn task_graph(app_toml: &Path, path: &Path) -> Result<()> {
let dot = File::create(path)?;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this prep for including the graph in the docs? I don't see it used anywhere.

Comment thread build/xtask/src/config.rs
pub app_config: String,
pub auxflash: Option<AuxFlashData>,
pub caboose: Option<CabooseConfig>,
pub docfile: Option<PathBuf>,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No one is using this yet, right?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see it's just Cosmo right now.

Comment thread build/xtask/src/aggro.rs
} => {
if !dest_url.starts_with("http") {
// TODO: rewrite relative to `https://github.com/oxidecomputer/hubris/blob/master/`?
// use _base to figure out relative paths, we might also need to
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

Comment thread build/xtask/src/aggro.rs
id,
})
}
// Bump down headings one notch, to allow for top level docs
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weirdly, I still see h1 headings for tasks in your sample file:

Image

Comment thread build/xtask/src/aggro.rs
buf: &mut String,
) -> Result<()> {
let mut mkdn = String::new();
writeln!(&mut mkdn, "# Task: \"{name}\" (`{}`)", task.name)?;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vibes:

Suggested change
writeln!(&mut mkdn, "# Task: \"{name}\" (`{}`)", task.name)?;
writeln!(&mut mkdn, "# `{name}` (`{}`)", task.name)?;

The task name is also used as an identifier in code, and I think it's overkill for the header to tell us it's a task.

Comment thread build/xtask/src/aggro.rs
let parser = pulldown_cmark::Parser::new_ext(&mkdn, PULLDOWN_OPTS);
html::push_html(buf, parser);

if let Some(readme) = cfg.docfile.as_ref() {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we try to find a README if this is empty, based on Cargo metadata?

(I'm fine with this being a later PR)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants